function map( data ) {
	var self = this;

	for( var i in data )
		self[i] = data[i];

	var hmap = [];
	var tw = config.tile.width;
	var th = config.tile.height;

	if( typeof self.events == 'undefined' )
		self.events = [];

	for( var y in self.events )
		for( var x in self.events[y] ) {
			var ev = new event( self, self.events[y][x] );
			self.events[y][x] = ev;

			if( vars[ev.id] && vars[ev.id] < 0 ) ev.remove();
			else ev.setPage( vars[ev.id] ? vars[ev.id] : 0 );
		}

	self.drawbuffer = function( mapbuffer, callback ) {
		chipsets.load( self.chipset, function ( chipset ) {
			var ctx, chipid, level;

			mapbuffer.lower.width = self.width*tw;
			mapbuffer.upper.width = self.width*tw;

			mapbuffer.lower.height = self.height*th;
			mapbuffer.upper.height = self.height*th;

			for( var x = 0; x < self.width; x++ ) hmap[x] = [];

			for( var l = 0; l < self.data.length; l++ )
				for( var x = 0; x < self.width; x++ )
					for( var y = 0; y < self.height; y++ )
						if( typeof self.data[l][x][y] != undefined && self.data[l][x][y] != null ) {
							chipid = self.data[l][x][y];
							level = chipset.level( chipid );

							if( level == 1 )
								hmap[x][y] = 1; // Same level as hero
							else if( level == 3 && ( y-1 < 0 || self.data[l][x][y-1] == chipid ))
								hmap[x][y] = 1; // Rooftile

							ctx = level > 1 ? mapbuffer.u : mapbuffer.l;
							chipset.tile( ctx, self.data[l][x][y] , x, y, self.data[l] );
						}

			callback();
		});
	};

	self.find = function( x, y ) {
		if( this.events[y] && this.events[y][x] )
			return this.events[y][x];
		else
			return false;
	}

	self.free = function( x, y ) {
		if( hmap[x] ) return !hmap[x][y];
		else return false;
	}

	self.valid = function( x, y ) {
		if( x < 0 || y < 0 ) return false;
		if( x >= this.width ) return false;
		if( y >= this.height ) return false;
		return true;
	}
};